STM32 多路ADC同时扫描采样 您所在的位置:网站首页 stm32 多路adc程序 STM32 多路ADC同时扫描采样

STM32 多路ADC同时扫描采样

2024-07-12 01:14| 来源: 网络整理| 查看: 265

背景

在项目实际应用中,刚好有需求需要使用多路ADC同时采样,这里就选择STM32 ADC多路ADC同时采样,这里简单说明下配置过程,以及使用步骤

原理图

如下图所示,使用四路ADC输入

ADC_Voltage -> 电压信号的采样,外部输入信号,交流电的输入信号,正选信号

ADC_Current -> 电流电流的采样,外部输入信号,交流电的输入信号,正选信号

ADC_Compensation ->      热敏电阻的采样,温度补偿

SCR_NTC ->      同样的热敏电阻的采样,温度补偿

一共使用上述四路ADC输入信号,进入STM32F103C8T6进行采样

外部输入电流、电压采用信号,这里做个保护电路

 NTC热敏电阻采样电路如下

 这里不仔细说明NTC补偿温度的过程,网上也比较多资料,这里侧重说明一下STM ADC的配置

软件设计

采用STM32F103C8T6 使用固件库开发方式

ADC初始化如下

定义DMA搬运ADC采样原始数据的到RAM的地址空间

#define SAMPL_TIMES_PRE_CHANNEL 1000 //每通道采样次数 #define NUM_OF_CHANNEL 4 //供4个通道 uint16_t __IO AD_Value[SAMPL_TIMES_PRE_CHANNEL][NUM_OF_CHANNEL]; //ADC转换结果,DMA目标地址

由于主时钟倍频到72MHZ,这里使用ADC1,首先6分频,主要是不需要特别高的采样率

1路、2路ADC信号,是正选信号,需要匹配其频率,这里经过计算的配置如下

3路、4路ADC信号,无所谓频率,所以只需要匹对1路、2路即可

这里采用独立模式连续多通道扫描模式,针对原理图中设计的

0、1、6、7通道进行扫描

根据需要也可以选择是否打开扫描完成后的中断,实际使用过程中,没有打开,因为感觉没啥用

如果有需要的话也是可以打开的。

打开扫描完成后的中断,需要注意,清除中断标志

void bspNTCAdcInit(void) { // NVIC_InitTypeDef NVIC_InitStructure; ADC_InitTypeDef ADC_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; DMA_InitTypeDef DMA_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); /* Configure ADC PA1 PA2 PA6 PA7 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; GPIO_Init(GPIOA, &GPIO_InitStructure); /* 配置ADC时钟,为PCLK2的8分频,即72/8=9MHz,ADC最大不超过14MHz */ //RCC_ADCCLKConfig(RCC_PCLK2_Div8); RCC_ADCCLKConfig(RCC_PCLK2_Div6); RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 , ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1 , ENABLE); /* ADC1 configuration ------------------------------------------------------*/ ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; /* 独立模式 */ ADC_InitStructure.ADC_ScanConvMode = ENABLE; /* 连续多通道模式 */ ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; /* 连续转换 */ ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; /* 转换不受外界决定 */ ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; /* 右对齐 */ ADC_InitStructure.ADC_NbrOfChannel = NUM_OF_CHANNEL; /* 扫描通道数 */ ADC_Init(ADC1, &ADC_InitStructure); /* ADC1 regular channe0 configuration */ //通过查找数据手册可知,PA5对应的是channel_5 转换时间为:(239.5+12.5)/9 = 28us ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_239Cycles5); ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_239Cycles5); ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 3, ADC_SampleTime_239Cycles5); /* ADC1,ADC通道x,规则采用顺序值为1,采样时间为239.5周期 */ ADC_RegularChannelConfig(ADC1, ADC_Channel_7, 4, ADC_SampleTime_239Cycles5); /* ADC1,ADC通道x,规则采用顺序值为2,采样时间为239.5周期 */ /* Enable the temperature sensor and vref internal channel */ //ADC_TempSensorVrefintCmd(ENABLE); ADC_DMACmd(ADC1, ENABLE);//开启ADC的DMA支持 /* Enable ADC1 */ ADC_Cmd(ADC1, ENABLE); /* Enable ADC1 reset calibaration register */ ADC_ResetCalibration(ADC1); /* Check the end of ADC1 reset calibration register */ while(ADC_GetResetCalibrationStatus(ADC1)); /* Start ADC1 calibaration */ ADC_StartCalibration(ADC1); /* Check the end of ADC1 calibration */ while(ADC_GetCalibrationStatus(ADC1)); /* Start ADC1 Software Conversion */ //ADC_SoftwareStartConvCmd(ADC1, ENABLE); DMA_DeInit(DMA1_Channel1); //将DMA的通道1寄存器重设为缺省值 DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&ADC1->DR; //DMA外设ADC基地址 DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&AD_Value; //DMA内存地址 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //内存作为数据传输的目的地 DMA_InitStructure.DMA_BufferSize = NUM_OF_CHANNEL * SAMPL_TIMES_PRE_CHANNEL; //DMA通道的DMA缓存大小 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设寄存器地址不变 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址寄存器递增 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //数据宽度为16位 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //数据宽度为16位 DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //工作在循环缓存模式 DMA_InitStructure.DMA_Priority = DMA_Priority_High; //DMA通道x拥有高优先级 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //DMA通道x没有设置为内存到内存传输 DMA_Init(DMA1_Channel1, &DMA_InitStructure); // // NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn; // NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 8;// 设置抢占优先级 // NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // NVIC_Init(&NVIC_InitStructure); DMA_Cmd(DMA1_Channel1, ENABLE); //启动DMA通道 // DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE); ADC_SoftwareStartConvCmd(ADC1, ENABLE); }

对采样的数据进行均值滤波

这里根据自己的需要,对采样的数据进行均值滤波

可以一起计算滤波,也可以分开计算,这个计算过程比较消耗资源,所以,我这里分开计算了

使用哪一路的ADC进行计算哪一路

只有需要更新ADC时才计算实际ADC的数值

void filter_0_1(void) { uint64_t sum = 0; uint16_t count , i; i = 0; for(count = 0; count < SAMPL_TIMES_PRE_CHANNEL; count += 1) { sum += AD_Value[count][i] * AD_Value[count][i]; //sum += AD_Value[count][i]; } after_filter[i]=sum / SAMPL_TIMES_PRE_CHANNEL; sum=0; //printf("i:%d,%4.2fv\r\n", i,((float)after_filter[i]/4095)*3.3); i = 1; for(count = 0; count < SAMPL_TIMES_PRE_CHANNEL; count += 1) { sum += AD_Value[count][i] * AD_Value[count][i]; //sum += AD_Value[count][i]; } after_filter[i]=sum / SAMPL_TIMES_PRE_CHANNEL; //printf("i:%d,%4.2fv\r\n", i,((float)after_filter[i]/4095)*3.3); } //static u8 ntct_fresh = 1; void filter_2_3(void) { uint32_t sum = 0; uint16_t count , i; i = 2; //if(ntct_fresh == 1) { for(count = 0; count < SAMPL_TIMES_PRE_CHANNEL; count += 1) { sum += AD_Value[count][i]; } after_filter[i]=sum / SAMPL_TIMES_PRE_CHANNEL; } sum=0; //printf("i:%d,%4.3fv\r\n", i,((float)after_filter[i]/4095)*3.3); // i = 3; // for(count = 0; count < SAMPL_TIMES_PRE_CHANNEL; count += 1) // { // sum += AD_Value[count][i]; // } // after_filter[i]=sum / SAMPL_TIMES_PRE_CHANNEL; // //printf("i:%d,%4.3fv\r\n", i,((float)after_filter[i]/4095)*3.3); }

如果打开DMA中断标识,需要清除中断标志

void DMA1_Channel1_IRQHandler(void) { portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; // uint16_t msg = MSG_SYS_ADC; if(DMA_GetFlagStatus(DMA1_FLAG_TC1)==SET) { DMA_ClearFlag(DMA1_FLAG_TC1); //xQueueSendFromISR( tempctrlxQueue, &msg, &xHigherPriorityTaskWoken ); } portEND_SWITCHING_ISR( xHigherPriorityTaskWoken ); }



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有